package services

import (
	"crypto/md5"
	"encoding/hex"
	"errors"
	mongodao "mygame/app/dao/mongoDao"
	retdata "mygame/app/structs/retData"
	"mygame/app/utils"
	redispkg "mygame/pkg/redisPkg"
	"strconv"
	"time"
)

type User struct{}

func (u User) UsernameLogin(username string, password string) (*retdata.Login, error) {
	//获取用户信息
	user, err := mongodao.User{}.GetUserByUsername(username)
	if err != nil {
		return nil, err
	}

	hash := md5.Sum([]byte(password))     // 计算 MD5 哈希
	md5Str := hex.EncodeToString(hash[:]) // 转换为十六进制字符串

	if user.Password != md5Str {
		return nil, errors.New("密码错误")
	}
	//redis存储token
	token := setToken(user.Uid)
	res := &retdata.Login{Uid: user.Uid, Token: token, Username: user.Username}
	return res, nil
}

func (u User) OpenidLogin(openid string) (*retdata.Login, error) {
	//获取用户信息
	user, err := mongodao.User{}.GetUserByOpenid(openid)
	if err != nil {
		return nil, err
	}
	//redis存储token
	token := setToken(user.Uid)
	res := &retdata.Login{Uid: user.Uid, Token: token, Username: user.Username}
	return res, nil
}

const (
	TOKEN_KEY         = "token:"
	TOKEN_TTL         = 60 * 60 * 12
	REFRESH_TOKEN_TTL = 60 * 60 * 24

	// TOKEN_TTL         = 10
	// REFRESH_TOKEN_TTL = 20
)

func setToken(userId int64) string {
	token := utils.GenerateToken(userId)
	refreshToken := utils.GetRefreshToken(token)
	tokenKey := TOKEN_KEY + token
	refreshTokenKey := TOKEN_KEY + refreshToken
	redispkg.Rdb.Set(redispkg.Ctx, tokenKey, userId, TOKEN_TTL*time.Second)
	redispkg.Rdb.Set(redispkg.Ctx, refreshTokenKey, userId, REFRESH_TOKEN_TTL*time.Second)

	return token
}

func (u User) CheckToken(token string) (int64, bool) {
	tokenKey := TOKEN_KEY + token
	hasToken := redispkg.Rdb.Get(redispkg.Ctx, tokenKey)
	userId := hasToken.Val()
	if hasToken.Err() == nil && hasToken.Val() != "" {
		num, err := strconv.ParseInt(userId, 10, 64)
		if err != nil {
			return 0, false
		}
		return num, true
	} else {
		refreshToken := utils.GetRefreshToken(token)
		refreshTokenKey := TOKEN_KEY + refreshToken
		hasRefreshToken := redispkg.Rdb.Get(redispkg.Ctx, refreshTokenKey)
		if hasRefreshToken.Err() == nil && hasRefreshToken.Val() != "" {
			userId = hasRefreshToken.Val()
			redispkg.Rdb.Set(redispkg.Ctx, tokenKey, userId, TOKEN_TTL*time.Second)
			redispkg.Rdb.Set(redispkg.Ctx, refreshTokenKey, userId, REFRESH_TOKEN_TTL*time.Second)
			num, err := strconv.ParseInt(userId, 10, 64)
			if err != nil {
				return 0, false
			}
			return num, true
		}
		return 0, false
	}
}

func (u User) GetUserInfo(userId int64) *retdata.User {
	user, _ := mongodao.User{}.GetUserByUid(userId)
	return &retdata.User{Uid: user.Uid, Username: user.Username}
}

func (u User) SaveData(uid int64, data map[string]interface{}) {
	mongodao.UserData{}.SaveData(uid, data)
}

func (u User) GetData(uid int64) map[string]interface{} {
	return mongodao.UserData{}.GetData(uid)
}
